import numpy as np

X = 2 * np.random.rand(100, 1)
y = 4 + 3 * X + np.random.randn(100, 1)
X_b = np.c_[np.ones((100, 1)), X]

n_epochs = 10000
m = 100
learning_rate = 0.001
batch_size = 10
num_batches = int(m / batch_size)

theta = np.random.randn(2, 1)

for epoch in range(n_epochs):
    arr = np.arange(len(X_b))
    np.random.shuffle(arr)
    X_b = X_b[arr]
    y = y[arr]
    for i in range(m):
        x_batch = X_b[i * batch_size:i * batch_size + num_batches]
        y_batch = y[i * batch_size:i * batch_size + num_batches]
        gradients = x_batch.T.dot(x_batch.dot(theta) - y_batch)
        theta -= learning_rate * gradients

print(theta)
